﻿//2024-1-30 Tuesday 20:01:43
//第14讲：深?理解指针(4)
//?录
//1. 回调函数是什么
//2. qsort使?举例
//3. qsort函数的模拟实现

//3. qsort函数的模拟实现
//void qsort(void* base, //待排序数据的起始位置
//	       void* sum,  //待排序数据的元素个数
//	       void* size,  //待排序数据的每个元素的大小
//	       int(*compar)(const void*, const void*)
//	       //函数指针 - 指针指向的函数是用来比较待排序数据中两个元素大小关系的
//          );

//qsort函数是库函数，直接可以使用
//qsort可以排序任意类型的数据，内部使用的是快速排序的方法

//我们现在已经学习过了冒泡排序
//今天我们想使用冒泡排序，来实现一个对任意类型能够排序的函数


//#include <stdio.h>
//
//void print_arr(int* arr, int sz)
//{
//	int i = 0;
//	
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//	printf("\n");
//}
//
//void bubble_sort(void* base, size_t sz, size_t width, int(*cmp)(const void* e1, const void* e2))
//{
//	//趟数
//	int i = 0;
//
//	for (i = 0; i < sz - 1; i++)
//	{
//		//一趟冒泡排序的过程
//		int j = 0;
//
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			//if (arr[j] > arr[j + 1])
//			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
//			{
//				//交换
//				//int tmp = arr[j];
//				//arr[j] = arr[j + 1];
//				//arr[j + 1] = tmp;
//			}
//		}
//	}
//}
//
//void Swap(char* buf1, char* buf2, size_t width);
//{
//	int i = 0;
//
//	for ( i = 0; i < )
//}
//void Swap(char* buf1, char* buf2, size_t width)
//{
//    int i = 0;
//    for (i = 0; i < width; i++)
//    {
//        char tmp = *buf1;
//        *buf1 = *buf2;
//        *buf2 = tmp;
//        buf1++;
//        buf2++;
//    }
//}
//
////比较方法，比较什么类型就用什么类型的比较方法
//int cmp_int(const void* e1, const void* e2)
//{
//	return *(int*)e1 - *(int*)e2;
//}
//
////测试bubble_sort排序整型数据
//void test()
//{
//	int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//
//	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int); //冒泡排序
//	print_arr(arr, sz);
//}
//
//int main()
//{
//	
//	return 0;
//}


//上面那些不会写了，









//2024-2-4 Sunday 18:42:24
//第15讲：深⼊理解指针(5)
//⽬录
//1. sizeof和strlen的对⽐
//2. 数组和指针笔试题解析
//3. 指针运算笔试题解析

//1. sizeof和strlen的对⽐
//1.1 sizeof

//#include <stdio.h>
//
//int main()
//{
//	int a = 0;
//
//	printf("%zd\n", sizeof(a));
//	printf("%zd\n", sizeof a);
//	printf("%zd\n", sizeof(int));
//	//printf("%zd\n", sizeof int); //error
//
//	//size_t : 是专门设计给sizeof的，表示sizeof的返回值类型
//
//	return 0;
//}


//1.2 strlen
//#include <stdio.h>
//#include <string.h>
//
//int main()
//{
//	char arr1[] = "abcedf";
//	char arr2[] = "abc\0edf";
//	char arr3[] = { 'a', 'b', 'c' };
// 
//	printf("%zd\n", strlen(arr1)); //6
//	printf("%zd\n", strlen(arr2)); //3
//	printf("%zd\n", strlen(arr3)); //随机值，去内存中看一下\0的位置
//
//	return 0;
//}


//#include <stdio.h>
//#include <string.h>
//
//int main()
//{
//	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//	int len = strlen(arr); //int*， 会报警告，My understanding: 总之：管你放什么，遇到\0就停止
//	//size_t strlen(const char* str)
//
//	printf("%zd\n", len);
//
//	//1
//	//0000 0000 0000 0000 0000 0000 0000 0001
//	//2进制 -> 16进制 2进制中的每4个0是16进制中的2个0
//	//00 00 00 01
//	//总结：数据在内存中是倒着存的
//
//	return 0;
//}


//#include <stdio.h>
//
//int main()
//{
//	short s = 10; //占2个字节
//	int i = 2;    //占4个字节
//	size_t n = sizeof(s = i + 4); //截断
//
//	printf("%zd\n", n); //2
//	printf("%zd\n", s); //6 - error
//
//	//sizeof : 在计算大小的时候，是根据类型推算的
//	//sizeof : 的操作数如果是一个表达式，表达式是不参与计算的！！！
//
//	return 0;
//}


//My undetstanding: 验证int在x64 / x86下的大小都是 4byte
//#include <stdio.h>
//
//int main()
//{
//	printf("%zd\n", sizeof(int));
//
//	return 0;
//}


//2024-2-5 Monday 15:21:44
//第15讲：深⼊理解指针(5)
//⽬录
//1. sizeof和strlen的对⽐
//2. 数组和指针笔试题解析
//3. 指针运算笔试题解析

//2. 数组和指针笔试题解析
//2.1 ⼀维数组
//#include <stdio.h>
//
//int main()
//{
//	//数组名的理解：
//	//数组名是首元素的地址
//	//但是有2个例外：
//	//1. sizeof(数组名)，数组名表示整个数组，计算的是整个数组的地址，单位是字节
//	//2. &数组名，数组名表示整个数组，取出的是整个数组的地址
//
//	int a[] = { 1,2,3,4 };
//
//	printf("%zd\n", sizeof(a)); //16
//
//	printf("%zd\n", sizeof(a + 0)); //4/8
//	//数组名a并没有单独放在sizeof内部，也没有&，
//	//所以：a就是数组首元素的地址，是地址大小就是 4/8个字节
//	//a+0 == &a[0]
//
//	printf("%zd\n", sizeof(*a)); //4
//	//a就是数组首元素的地址， a == &a[0]
//	//*a其实就是第一个元素，也就是a[0]，大小就是4个字节
//
//	printf("%zd\n", sizeof(a + 1)); //4/8
//	//a就是数组首元素的地址(&a[0] -- int*), a+1 --> &a[1]
//	//a+1就是第2个元素的地址
//
//	printf("%zd\n", sizeof(a[1])); //4
//	//计算第2个元素的大小，单位是字节 - 4
//	printf("%zd\n", sizeof(&a)); //4/8
//	//&a - 取出的是数组的地址，但是数组的地址也是地址，是地址大小就是4/8个字节
//
//	printf("%zd\n", sizeof(*&a)); //16  (4/8 error)
//	//printf("%zd\n", sizeof(a)); //16
//	//&a - int(*p)[4] = &a;
//	//sizeof(*p) 访问1个数组的大小
//	//sizeof(p+1)，跳过1个数组的大小
//
//	//My understanding: 第1种方法： * 和 &相抵消，剩下sizeof(a)，此时计算的是整个数组
//	//                :   2     ： 整个数组的地址解引用，找到整个数组，整个数组的大小是16个字节
//
//	printf("%zd\n", sizeof(&a + 1)); //4/8
//	//&a+1是跳过整个数组后的地址，是地址大小就是 4/8个字节
//
//	printf("%zd\n", sizeof(&a[0])); //4/8
//	//首元素的地址 4/8
//
//	printf("%zd\n", sizeof(&a[0] + 1)); //4/8
//	//第2个元素的地址
//	//&a[1]
//	//&a[1] - int*
//
//	return 0;
//}


//2.2 字符数组
#include <stdio.h>

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	//[ a b c d e f ]

	printf("%d\n", sizeof(arr)); //6

	printf("%d\n", sizeof(arr + 0)); //4/8
	//arr是数组首元素的地址，arr+0 还是首元素的地址， 是地址大小就是4/8个字节
	//char*

	printf("%d\n", sizeof(*arr)); //1
	//arr是数组首元素的地址， *arr就是首元素，就占1个字符大小就是1个字节

	printf("%d\n", sizeof(arr[1])); //1
	//arr[1]就是数组的第2个元素，大小是1个字节

	printf("%d\n", sizeof(&arr)); //4/8
	//&arr是数组的地址，数组的地址也是地址，大小就是4/8个字节

	printf("%d\n", sizeof(&arr + 1)); //4/8
	//&arr+1是跳过整个数组，指向f的后面 4/8

	printf("%d\n", sizeof(&arr[0] + 1)); //4/8
	//&arr[0]是数组首元素的地址，&arr[0]+1就是第2个元素的地址 4/8

	return 0;
}





